<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="utf-8">
    <title>三川数字人（智能对话）</title>
    <meta name="renderer" content="webkit">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport"
          content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=0">
    <link rel="shortcut icon" type="image/x-icon" href="../logo.png"/>
    <link rel="stylesheet" href="layui/css/layui.css">
</head>
<body>
<script src="layui/layui.js"></script>
<script src="audio.recorder.js"></script>
<script>
    const SPEAK_DURATION = 30;
    let SESSION_ID = '';
    layui.config({
        base: 'layim/mobile/'
        , layimResPath: 'layim/res/'
    }).extend({
        'layim-mobile': 'layim-mobile'
        , 'layer-mobile': 'layer-mobile'
        , 'zepto': 'zepto'
    }).use('layim-mobile', function () {
        const layim = layui['layim-mobile'];
        const layer = layui['layer-mobile'];
        const zepto = layui['zepto'];
        const chat = {
            id: '@'
            , username: document.title
            , name: document.title
            , type: '@chat@'
            , avatar: '../logo.png'
        };
        const audio = new Recorder({
            sampleRate: 16000
            , sampleBits: 16
            , numChannels: 1
        });
        const base64 = function (blob) {
            return new Promise(function (resolve, reject) {
                const reader = new FileReader();
                reader.onload = function () {
                    resolve(reader.result.split(',')[1])
                };
                reader.onerror = function () {
                    reject(reader.error);
                };
                reader.readAsDataURL(blob);
            });
        };
        const load = function () {
            return layer.open({
                id: 'loading'
                , type: 2
                , shadeClose: false
            });
        };
        const toast = function (msg) {
            return layer.open({
                time: 3
                , skin: 'msg'
                , content: msg
            });
        };
        const tts = function (text) {
            const audio = document.createElement("audio");
            audio.src = '/api/tts?text=' + text;
            audio.play();
        };
        layim.config({
            init: {
                mine: {
                    id: '@me@'
                    , username: '我'
                }
            }
            , tool: [{
                alias: 'audio'
                , title: '录音/麦克风'
                , iconUnicode: '&#xe6dc;'
            }]
            , chatTitleColor: '#c00'
            , title: document.title
            , voice: false
            , brief: true
        });
        layim.on('tool(audio)', function (insert, send) {
            try {
                audio.start().then(function () {
                    console.log('开始录音...');
                    const index = layer.open({
                        id: 'recording'
                        , type: 2
                        , content: '<span id="recording">录音中...（' + SPEAK_DURATION + '秒）<span>'
                        , end: function () {
                            console.log('停止录音...');
                            audio.stop();
                            base64(audio.getPCMBlob()).then(function (base64) {
                                let index;
                                zepto.ajax({
                                    type: 'POST'
                                    , url: '/api/asr'
                                    , data: base64
                                    , beforeSend: function () {
                                        index = load();
                                    }
                                    , success: function (data) {
                                        console.log(data);
                                        if (data.err_no !== 0) {
                                            toast('语音识别失败（' + data.err_no + ':' + data.err_msg + '）');
                                        } else {
                                            insert(data.result[0]);
                                            send();
                                        }
                                    }
                                    , error: function (xhr, status, error) {
                                        toast('语音识别请求异常，请重试！（' + (error || status) + '）');
                                    }
                                    , complete: function () {
                                        layer.close(index);
                                    }
                                });
                            }).catch(function (e) {
                                toast('录音失败（' + e + '）');
                            });
                        }
                    });
                    audio.onprocess = function (duration) {
                        console.log('录音中...' + duration + 's');
                        zepto('#recording').html('录音中...（' + parseInt(SPEAK_DURATION - duration) + '秒）按下停止');
                        if (duration > SPEAK_DURATION) {
                            layer.close(index);
                        }
                    };
                }).catch(function (e) {
                    toast('麦克风打开失败（' + e + '）');
                });
            } catch (e) {
                toast('麦克风打开异常（' + e + '）');
            }
        });
        layim.on('sendMessage', function (data) {
            let index;
            zepto.ajax({
                type: 'GET'
                , url: '/api/chat?session_id=' + SESSION_ID + '&query=' + data.mine.content
                , beforeSend: function () {
                    index = load();
                }
                , success: function (data) {
                    console.log(data);
                    if (data.error_code !== 0) {
                        toast('智能对话失败（' + data.error_code + ':' + data.error_msg + '）');
                    } else {
                        SESSION_ID = data.result.session_id;
                        const responses = data.result.response_list || data.result.responses;
                        const actions = responses[0].action_list || responses[0].actions;
                        chat.content = actions[0].say;
                        layim.getMessage(chat);
                        tts(chat.content);
                    }
                }
                , error: function (xhr, status, error) {
                    toast('智能对话请求异常，请重试！（' + (error || status) + '）');
                }
                , complete: function () {
                    layer.close(index);
                }
            });
        });
        layim.on('chatChange', function () {
            zepto('.layim-chat-tool').hide();
            zepto('.layim-tool-face').hide();
            zepto('.layim-chat-footer').css({'left': '0px', 'height': '60px'});
            zepto('.layim-chat-send').prepend('<button class="layui-btn" style="color:black;background:rgb(255,0,0,0);margin-left:0px;padding:0px;" layim-event="extend" lay-filter="audio">'
                + '<i class="layui-icon layui-icon-mike" style="font-size:30px;"></i></button>');
        });
        layim.on('back', function () {
            layim.chat(chat);
        });
        layim.chat(chat);
    });
</script>
</body>
</html>
